package com.whfc.mach.service.impl;

import cn.hutool.core.text.StrJoiner;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.whfc.common.enums.FenceType;
import com.whfc.common.enums.HandleFlag;
import com.whfc.common.exception.BizException;
import com.whfc.common.geometry.GeometryUtil;
import com.whfc.common.geometry.Point;
import com.whfc.common.geometry.Polygon;
import com.whfc.common.result.ListData;
import com.whfc.common.result.PageData;
import com.whfc.common.result.ResultEnum;
import com.whfc.common.util.AssertUtil;
import com.whfc.common.util.PageUtil;
import com.whfc.entity.dto.msg.AppMsgToUserDTO;
import com.whfc.entity.dto.msg.AppWarnMsgRecDTO;
import com.whfc.mach.dao.*;
import com.whfc.mach.dto.AppMachDTO;
import com.whfc.mach.dto.MachOperEmpDTO;
import com.whfc.mach.dto.warn.*;
import com.whfc.mach.entity.AppMachWarnRecord;
import com.whfc.mach.entity.AppMachWarnRule;
import com.whfc.mach.entity.AppMachWarnRuleObject;
import com.whfc.mach.enums.AppMachWarnRuleType;
import com.whfc.mach.manager.warn.AppWarnManager;
import com.whfc.mach.manager.warn.AppWarnManagerFactory;
import com.whfc.mach.param.warn.*;
import com.whfc.mach.service.AppMachWarnService;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import java.util.*;

/**
 * @author sun_guodong
 * @date 2021-08-04
 */
@DubboService(interfaceClass = AppMachWarnService.class, version = "1.0.0")
public class AppMachWarnServiceImpl implements AppMachWarnService {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String PARAM_NAME = "value";

    @Autowired
    private AppMachWarnRecordMapper appMachWarnRecordMapper;

    @Autowired
    private AppMachWarnRuleMapper appMachWarnRuleMapper;

    @Autowired
    private AppMachWarnRuleTimeMapper appMachWarnRuleTimeMapper;

    @Autowired
    private AppMachWarnRuleObjectMapper appMachWarnRuleObjectMapper;

    @Autowired
    private AppMachWarnRuleUserMapper appMachWarnRuleUserMapper;

    @Autowired
    private AppMachWarnRuleChannelMapper appMachWarnRuleChannelMapper;

    @Autowired
    private AppMachOperEmpMapper appMachOperEmpMapper;

    @Autowired
    private AppWarnManagerFactory appWarnManagerFactory;

    @Override
    public AppMachWarnCountDTO warnNumStatic(Integer deptId, Integer state, Date startTime, Date endTime) throws BizException {
        logger.info("获取设备报警统计数据服务,deptId:{},state:{},startTime:{},endTime:{}", deptId, state, startTime, endTime);
        /*
        List<Integer> ruleTypeList = appMachWarnRecordMapper.selectRuleTypeList(deptId, null, null, state, startTime, endTime);
        AppMachWarnCountDTO appMachWarnCountDTO = new AppMachWarnCountDTO();
        int idleNum = 0;
        int workNum = 0;
        int stopNum = 0;
        int speedNum = 0;
        int deviceWarnNum = 0;
        int oilPosWarnNum = 0;
        int fenceWarnNum = 0;
        int rotationWarnNum = 0;
        int enginWarnNum = 0;
        int forceWarnNum = 0;
        for (Integer ruleType : ruleTypeList) {
            if (AppMachWarnRuleType.IDLE.value().equals(ruleType)) {
                idleNum += 1;
            } else if (AppMachWarnRuleType.WORK.value().equals(ruleType)) {
                workNum += 1;
            } else if (AppMachWarnRuleType.STOP.value().equals(ruleType)) {
                stopNum += 1;
            } else if (AppMachWarnRuleType.SPEED.value().equals(ruleType)) {
                speedNum += 1;
            } else if (AppMachWarnRuleType.DEVICE.value().equals(ruleType)) {
                deviceWarnNum += 1;
            } else if (AppMachWarnRuleType.OILPOS.value().equals(ruleType)) {
                oilPosWarnNum += 1;
            } else if (AppMachWarnRuleType.FENCE.value().equals(ruleType)) {
                fenceWarnNum += 1;
            } else if (AppMachWarnRuleType.ROTATION.value().equals(ruleType)) {
                rotationWarnNum += 1;
            } else if (AppMachWarnRuleType.ENGINE.value().equals(ruleType)) {
                enginWarnNum += 1;
            } else if (AppMachWarnRuleType.FORCE.value().equals(ruleType)) {
                forceWarnNum += 1;
            }
        }
         */

        Map<Integer, Integer> map = new HashMap<>();
        List<AppMachKVDTO> list = appMachWarnRecordMapper.selectAppMachKVDTO(deptId, null, null, state, startTime, endTime);
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(v -> map.put(v.getK(), v.getV()));
        }

        AppMachWarnCountDTO appMachWarnCountDTO = new AppMachWarnCountDTO();
        int idleNum = map.getOrDefault(AppMachWarnRuleType.IDLE.value(), 0);
        int workNum = map.getOrDefault(AppMachWarnRuleType.WORK.value(), 0);
        int stopNum = map.getOrDefault(AppMachWarnRuleType.STOP.value(), 0);

        int speedNum = map.getOrDefault(AppMachWarnRuleType.SPEED.value(), 0);
        int deviceWarnNum = map.getOrDefault(AppMachWarnRuleType.DEVICE.value(), 0);
        int oilPosWarnNum = map.getOrDefault(AppMachWarnRuleType.OILPOS.value(), 0);

        int fenceWarnNum = map.getOrDefault(AppMachWarnRuleType.FENCE.value(), 0);
        int rotationWarnNum = map.getOrDefault(AppMachWarnRuleType.ROTATION.value(), 0);
        int enginWarnNum = map.getOrDefault(AppMachWarnRuleType.ENGINE.value(), 0);
        int forceWarnNum = map.getOrDefault(AppMachWarnRuleType.FORCE.value(), 0);

        appMachWarnCountDTO.setIdleWarnNum(idleNum);
        appMachWarnCountDTO.setWorkWarnNum(workNum);
        appMachWarnCountDTO.setStopWarnNum(stopNum);
        appMachWarnCountDTO.setSpeedWarnNum(speedNum);
        appMachWarnCountDTO.setFenceWarnNum(fenceWarnNum);
        appMachWarnCountDTO.setDeviceWarnNum(deviceWarnNum);
        appMachWarnCountDTO.setOilPosWarnNum(oilPosWarnNum);
        appMachWarnCountDTO.setRotationWarnNum(rotationWarnNum);
        appMachWarnCountDTO.setEngineWarnNum(enginWarnNum);
        appMachWarnCountDTO.setForceWarnNum(forceWarnNum);
        appMachWarnCountDTO.setWarnNum(idleNum + workNum + stopNum + speedNum + fenceWarnNum + oilPosWarnNum + deviceWarnNum + rotationWarnNum + enginWarnNum + forceWarnNum);
        return appMachWarnCountDTO;
    }
    public Map<Integer, Integer> warnNumStaticV2(Integer deptId, Integer state, Date startTime, Date endTime) throws BizException {
        logger.info("获取设备报警统计数据服务,deptId:{},state:{},startTime:{},endTime:{}", deptId, state, startTime, endTime);
        List<Integer> ruleTypeList = appMachWarnRecordMapper.selectRuleTypeList(deptId, null, null, state, startTime, endTime);
        Map<Integer, Integer> ret = new HashMap<>();
        ret.put(-1,ruleTypeList.size());
        for (Integer ruleType : ruleTypeList) {
            Integer orDefault = ret.getOrDefault(ruleType, 0);
            ret.put(ruleType,++orDefault);

        }
        return ret;
    }

    @Override
    public PageData<AppWarnRuleDTO> ruleList(Integer pageNum, Integer pageSize, Integer ruleType, String keyword, Integer deptId, Integer enableFlag) throws BizException {
        logger.info("获取报警规则列表服务,pageNum:{},pageSize:{},ruleType:{},keyword:{},deptId:{},enableFlag:{}",
                pageNum, pageSize, ruleType, keyword, deptId, enableFlag);
        PageHelper.startPage(pageNum, pageSize);
        List<AppWarnRuleDTO> list = appMachWarnRuleMapper.selectRuleList(deptId, ruleType, keyword, enableFlag);
        PageHelper.clearPage();

        for (AppWarnRuleDTO appWarnRuleDTO : list) {
            Integer warnRuleType = appWarnRuleDTO.getRuleType();
            String ruleParam = appWarnRuleDTO.getRuleParam();

            if (AppMachWarnRuleType.FENCE.value().equals(warnRuleType)) {
                // 电子围栏
                MachWarnFenceDTO machWarnFenceDTO = JSON.parseObject(ruleParam, MachWarnFenceDTO.class);
                this.decodeFence(machWarnFenceDTO);
                appWarnRuleDTO.setType(machWarnFenceDTO.getType());
                appWarnRuleDTO.setCenterPoint(machWarnFenceDTO.getCenterPoint());
                appWarnRuleDTO.setRadius(machWarnFenceDTO.getRadius());
                appWarnRuleDTO.setPolygonPointList(machWarnFenceDTO.getPolygonPointList());
            } else if (AppMachWarnRuleType.ROTATION.value().equals(warnRuleType)) {
                // 倾角报警
                MachRotationRuleDTO machRotationRuleDTO = JSON.parseObject(ruleParam, MachRotationRuleDTO.class);
                appWarnRuleDTO.setMachRotationRuleDTO(machRotationRuleDTO);
            } else {
                appWarnRuleDTO.setRuleValue(JSON.parseObject(ruleParam).getString(PARAM_NAME));
            }
            // 查找时间段
            List<AppWarnTimeDTO> timeList = appMachWarnRuleTimeMapper.selectByRuleId(appWarnRuleDTO.getRuleId());
            appWarnRuleDTO.setTimeList(timeList);


            List<AppMsgToUserDTO> userList = appMachWarnRuleUserMapper.selectByRuleId(appWarnRuleDTO.getRuleId());
            List<Integer> msgChannelList = appMachWarnRuleChannelMapper.selectByRuleId(appWarnRuleDTO.getRuleId());
            appWarnRuleDTO.setUserList(userList);
            appWarnRuleDTO.setMsgChannelList(msgChannelList);
        }
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void ruleDel(Integer ruleId) throws BizException {
        logger.info("删除报警规则服务,ruleId:{}", ruleId);
        AppMachWarnRule data = appMachWarnRuleMapper.selectByPrimaryKey(ruleId);
        if (data == null || data.getDelFlag() == 1) {
            return;
        }
        AssertUtil.isTrue(data.getEnableFlag() != null && data.getEnableFlag() == 1, "报警规则启用状态下不能删除");
        List<String> objectIdList = appMachWarnRuleObjectMapper.selectByRuleId(ruleId);
        if (objectIdList.size() > 0) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该报警规则下有报警对象，不能删除");
        }
        appMachWarnRuleMapper.deleteLogicById(ruleId);
        appMachWarnRuleObjectMapper.deleteByRuleId(ruleId);
    }

    @Override
    public void enable(AppWarnEnableParam param) throws BizException {
        logger.info("启用/禁用报警规则服务,param:{}", param.toString());
        Integer enableFlag = param.getEnableFlag();
        Integer ruleId = param.getRuleId();
        appMachWarnRuleMapper.updateEnableFlagByRuleId(ruleId, enableFlag);
    }

    @Override
    public void ruleAdd(AppWarnRuleAddParam param) throws BizException {
        logger.info("添加报警规则服务,param:{}", param.toString());
        Integer deptId = param.getDeptId();
        Integer ruleType = param.getRuleType();
        String ruleValue = param.getRuleValue();
        String ruleParam = this.getRuleParam(ruleType, param.getType(), param.getRadius(), param.getCenterPoint(), param.getPolygonPointList(), param.getMachRotationRule(), ruleValue);
        // 新增报警规则
        AppMachWarnRule rule = new AppMachWarnRule();
        rule.setDeptId(deptId);
        rule.setRuleType(ruleType);
        rule.setRuleName(param.getName());
        rule.setRuleParam(ruleParam);
        appMachWarnRuleMapper.insertSelective(rule);

    }

    @Override
    public void ruleEdit(AppWarnRuleEditParam param) throws BizException {
        logger.info("编辑报警规则服务,param:{}", param.toString());
        Integer ruleId = param.getRuleId();
        String name = param.getName();
        Integer ruleType = param.getRuleType();
        String ruleParam = this.getRuleParam(ruleType, param.getType(), param.getRadius(), param.getCenterPoint(), param.getPolygonPointList(), param.getMachRotationRule(), param.getRuleValue());
        // 参数校验
        AppMachWarnRule rule = appMachWarnRuleMapper.selectByPrimaryKey(ruleId);
        if (rule == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "未找到该报警规则");
        }
        // 更新报警规则
        rule.setId(ruleId);
        rule.setRuleName(name);
        rule.setRuleParam(ruleParam);
        appMachWarnRuleMapper.updateByPrimaryKeySelective(rule);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setTime(AppWarnSetTimeParam param) throws BizException {
        logger.info("设置报警时间段服务,param:{}", param.toString());
        Integer ruleId = param.getRuleId();
        appMachWarnRuleTimeMapper.deleteByRuleId(ruleId);
        List<AppWarnTimeDTO> timeList = param.getTimeList();
        if (timeList != null && timeList.size() > 0) {
            for (AppWarnTimeDTO warnTimeDTO : timeList) {
                warnTimeDTO.setRuleId(ruleId);
            }
            appMachWarnRuleTimeMapper.batchInsert(timeList);
        }
    }

    @Override
    public AppWarnMsgRecDTO userList(Integer ruleId) throws BizException {
        logger.info("获取接收报警消息的用户列表服务,ruleId:{}", ruleId);
        List<AppMsgToUserDTO> userList = appMachWarnRuleUserMapper.selectByRuleId(ruleId);
        List<Integer> msgChannelList = appMachWarnRuleChannelMapper.selectByRuleId(ruleId);
        AppWarnMsgRecDTO appWarnMsgRecDTO = new AppWarnMsgRecDTO();
        appWarnMsgRecDTO.setMsgChannelList(msgChannelList);
        appWarnMsgRecDTO.setUserList(userList);
        return appWarnMsgRecDTO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void userAdd(AppWarnSetUserParam param) throws BizException {
        logger.info("设置消息接收人和接收的方式服务,param:{}", param.toString());
        Integer ruleId = param.getRuleId();
        // 消息联系人
        appMachWarnRuleUserMapper.deleteByRuleId(ruleId);
        List<AppMsgToUserDTO> userIdList = param.getUserList();
        if (userIdList != null && userIdList.size() > 0) {
            for (AppMsgToUserDTO warnUserDTO : userIdList) {
                warnUserDTO.setRuleId(ruleId);
            }
            appMachWarnRuleUserMapper.batchInsert(userIdList);
        }

        // 消息渠道
        appMachWarnRuleChannelMapper.deleteByRuleId(ruleId);
        List<Integer> msgChannelList = param.getMsgChannelList();
        if (!msgChannelList.isEmpty()) {
            appMachWarnRuleChannelMapper.batchInsert(ruleId, msgChannelList);
        }
    }

    @Override
    public ListData<AppMachDTO> objectList(Integer ruleId) throws BizException {
        logger.info("查找已设置的报警对象列表服务,ruleId:{}", ruleId);
        List<AppMachDTO> list = appMachWarnRuleObjectMapper.selectMachByRuleId(ruleId);
        return new ListData<>(list);
    }

    @Override
    public ListData<AppMachDTO> getMachList(Integer ruleId) throws BizException {
        logger.info("查找可供选择的报警对象列表服务,ruleId:{}", ruleId);
        AppMachWarnRule appMachWarnRule = appMachWarnRuleMapper.selectByPrimaryKey(ruleId);
        if (appMachWarnRule == null) {
            throw new BizException(ResultEnum.PARAM_ERROR.getCode(), "该报警规则不存在");
        }
        Integer deptId = appMachWarnRule.getDeptId();
        Integer ruleType = appMachWarnRule.getRuleType();
        List<AppMachDTO> list = appMachWarnRuleObjectMapper.selectAvailableMach(deptId, ruleType);
        return new ListData<>(list);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void objectAdd(AppWarnMachAddParam param) throws BizException {
        logger.info("添加报警对象服务,param:{}", param.toString());
        Integer ruleId = param.getRuleId();
        AppMachWarnRule rule = appMachWarnRuleMapper.selectByPrimaryKey(ruleId);
        if (rule == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该报警规则不存在");
        }
        appMachWarnRuleObjectMapper.deleteByRuleId(ruleId);

        List<Integer> machIdList = param.getMachIdList();
        if (machIdList == null || machIdList.size() == 0) {
            return;
        }
        Integer ruleType = rule.getRuleType();
        List<AppMachWarnRuleObject> list = new ArrayList<>(machIdList.size());
        for (Integer machId : machIdList) {
            AppMachWarnRuleObject appMachWarnRuleObject = new AppMachWarnRuleObject();
            appMachWarnRuleObject.setRuleId(ruleId);
            appMachWarnRuleObject.setObjectId(String.valueOf(machId));
            appMachWarnRuleObject.setRuleType(ruleType);
            list.add(appMachWarnRuleObject);
        }
        appMachWarnRuleObjectMapper.batchInsert(list);
    }

    @Override
    public PageData<AppWarnMachRecordDTO> recordList(Integer pageNum, Integer pageSize, Integer deptId, Integer state, Integer ruleType, Date startTime, Date endTime) throws BizException {
        logger.info("报警记录列表服务,pageNum:{},pageSize:{},deptId:{},state:{},ruleType:{},startTime:{},endTime:{}",
                pageNum, pageSize, deptId, state, ruleType, startTime, endTime);
        PageHelper.startPage(pageNum, pageSize);
        List<AppWarnMachRecordDTO> list = appMachWarnRecordMapper.selectByDeptId(deptId, state, ruleType, startTime, endTime);
        for (AppWarnMachRecordDTO warnMachRecordDTO : list) {
            warnMachRecordDTO.setId(warnMachRecordDTO.getWarnId());
            String triggerParam = warnMachRecordDTO.getTriggerParam();
            String ruleParam = warnMachRecordDTO.getRuleParam();

            MachWarnCheckDTO machWarnCheckDTO = JSON.parseObject(triggerParam, MachWarnCheckDTO.class);
            warnMachRecordDTO.setMachCode(machWarnCheckDTO.getMachCode());
            warnMachRecordDTO.setMachTypeName(machWarnCheckDTO.getMachTypeName());
            warnMachRecordDTO.setMachModelName(machWarnCheckDTO.getMachModelName());
            warnMachRecordDTO.setLat(machWarnCheckDTO.getLat());
            warnMachRecordDTO.setLng(machWarnCheckDTO.getLng());


            AppMachWarnRuleType appMachWarnRuleType = AppMachWarnRuleType.parseValue(warnMachRecordDTO.getRuleType());
            warnMachRecordDTO.setRuleName(appMachWarnRuleType.tittle());

            String ruleDesc = generateRuleDesc(appMachWarnRuleType, ruleParam);
            warnMachRecordDTO.setDetail(generateWarnDesc(appMachWarnRuleType, machWarnCheckDTO, ruleDesc));


        }
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }

    @Override
    public void recordHandle(AppWarnHandleParam request) throws BizException {
        logger.info("处理报警服务,param:{}", request.toString());
        AppMachWarnRecord record = new AppMachWarnRecord();
        record.setId(request.getWarnId());
        record.setHandleRemark(request.getHandleRemark());
        record.setHandleResult(request.getHandleResult());
        record.setHandleTime(new Date());
        record.setState(HandleFlag.HANDLE.getValue());
        record.setHandleUserId(request.getUserId());
        record.setHandleUserName(request.getUserName());
        appMachWarnRecordMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public void batchHandle(AppWarnBatchHandleParam param) throws BizException {
        logger.info("批量处理报警服务,param:{}", param.toString());
        List<Integer> warnIdList = param.getWarnIdList();
        String handleRemark = param.getHandleRemark();
        String handleResult = param.getHandleResult();
        Integer userId = param.getUserId();
        String userName = param.getUserName();
        appMachWarnRecordMapper.batchUpdateState(warnIdList, handleResult, handleRemark, userId, userName);
    }

    @Override
    public void del(AppWarnBatchDelParam param) throws BizException {
        logger.info("删除报警服务,param:{}", param.toString());
        // 删除报警记录
        appMachWarnRecordMapper.deleteLogic(param.getWarnIdList());
    }

    @Override
    public AppWarnDetailDTO recordDetail(Integer id) throws BizException {
        logger.info("报警详情服务,id:{}", id);
        AppMachWarnRecord machWarnRecord = appMachWarnRecordMapper.selectByPrimaryKey(id);
        if (machWarnRecord == null) {
            throw new BizException(ResultEnum.FAILURE.getCode(), "该报警不存在");
        }
        Integer ruleType = machWarnRecord.getRuleType();
        AppWarnDetailDTO data = new AppWarnDetailDTO();

        data.setHandleRemark(machWarnRecord.getHandleRemark());
        data.setHandleResult(machWarnRecord.getHandleResult());
        data.setHandleState(machWarnRecord.getState());
        data.setHandleTime(machWarnRecord.getHandleTime());
        data.setHandleUserName(machWarnRecord.getHandleUserName());
        data.setTriggerTime(machWarnRecord.getTriggerTime());
        data.setRuleType(ruleType);

        // 报警对象基本信息
        String triggerParam = machWarnRecord.getTriggerParam();
        MachWarnCheckDTO machWarnCheckDTO = JSON.parseObject(triggerParam, MachWarnCheckDTO.class);
        data.setMachCode(machWarnCheckDTO.getMachCode());
        data.setMachType(machWarnCheckDTO.getMachType());
        data.setMachTypeName(machWarnCheckDTO.getMachTypeName());
        data.setMachModelName(machWarnCheckDTO.getMachModelName());
        data.setLat(machWarnCheckDTO.getLat());
        data.setLng(machWarnCheckDTO.getLng());
        data.setTriggerValue(machWarnCheckDTO.getTriggerValue());
        // 查找操作手信息
        List<MachOperEmpDTO> operators = appMachOperEmpMapper.selectByMachId(machWarnCheckDTO.getMachId());
        data.setOperatorList(operators);
        // 报警规则
        String ruleParam = machWarnRecord.getRuleParam();
        if (AppMachWarnRuleType.FENCE.value().equals(ruleType)) {
            // 电子围栏
            MachWarnFenceDTO machWarnFenceDTO = JSON.parseObject(ruleParam, MachWarnFenceDTO.class);
            this.decodeFence(machWarnFenceDTO);
            data.setType(machWarnFenceDTO.getType());
            data.setCenterPoint(machWarnFenceDTO.getCenterPoint());
            data.setRadius(machWarnFenceDTO.getRadius());
            data.setPointList(machWarnFenceDTO.getPolygonPointList());
        } else if (AppMachWarnRuleType.ROTATION.value().equals(ruleType)) {
            // 倾角报警
            MachRotationRuleDTO machRotationRuleDTO = JSON.parseObject(ruleParam, MachRotationRuleDTO.class);
            data.setMachRotationRuleDTO(machRotationRuleDTO);
        } else {
            data.setRuleValue(JSON.parseObject(ruleParam).getString(PARAM_NAME));
        }
        List<AppWarnTimeDTO> timeList = appMachWarnRuleTimeMapper.selectByRuleId(machWarnRecord.getRuleId());
        data.setTimeList(timeList);

        AppMachWarnRuleType appMachWarnRuleType = AppMachWarnRuleType.parseValue(data.getRuleType());
        data.setRuleName(appMachWarnRuleType.tittle());

        String ruleDesc = generateRuleDesc(appMachWarnRuleType, ruleParam);
        data.setRuleDesc(ruleDesc);
        data.setDetail(generateWarnDesc(appMachWarnRuleType, machWarnCheckDTO, ""));
        return data;
    }

    @Override
    public Integer getWarnNum(List<Integer> deptIds, Date startTime, Date endTime) throws BizException {
        logger.info("查询大屏设备报警数服务,deptIds:{},startTime:{},endTime:{}", deptIds, startTime, endTime);
        return appMachWarnRecordMapper.countWarnNum(deptIds, startTime, endTime);
    }

    @Override
    public List<Integer> getWarnRuleTypeList(List<Integer> machIds, List<Integer> ruleTypes, Date startTime, Date endTime) throws BizException {
        logger.info("查询报警记录中的报警类型服务,machIds:{},ruleTypes:{},startTime:{},endTime:{}",
                machIds, ruleTypes, startTime, endTime);
        return appMachWarnRecordMapper.selectRuleTypeList(null, machIds, ruleTypes, null, startTime, endTime);
    }

    @Override
    public PageData<AppWarnMachRecordDTO> getMachWarnList(List<Integer> machIds, List<Integer> ruleTypes, Date startTime, Date endTime, Integer pageNum, Integer pageSize) throws BizException {
        logger.info("国网设备报警记录列表服务,machIds:{},ruleTypes:{},startTime:{},endTime:{},pageNum:{},pageSize:{}",
                machIds, ruleTypes, startTime, endTime, pageNum, pageSize);
        PageHelper.startPage(pageNum, pageSize);
        List<AppWarnMachRecordDTO> list = appMachWarnRecordMapper.selectMachWarnList(machIds, ruleTypes, startTime, endTime);
        for (AppWarnMachRecordDTO warnMachRecordDTO : list) {
            warnMachRecordDTO.setId(warnMachRecordDTO.getWarnId());
            String triggerParam = warnMachRecordDTO.getTriggerParam();
            MachWarnCheckDTO machWarnCheckDTO = JSON.parseObject(triggerParam, MachWarnCheckDTO.class);
            warnMachRecordDTO.setMachCode(machWarnCheckDTO.getMachCode());
            warnMachRecordDTO.setMachTypeName(machWarnCheckDTO.getMachTypeName());
            warnMachRecordDTO.setMachModelName(machWarnCheckDTO.getMachModelName());
            warnMachRecordDTO.setLat(machWarnCheckDTO.getLat());
            warnMachRecordDTO.setLng(machWarnCheckDTO.getLng());
            warnMachRecordDTO.setTriggerValue(machWarnCheckDTO.getTriggerValue());
        }
        PageHelper.clearPage();
        return PageUtil.pageData(PageInfo.of(list));
    }


    /**
     * 解码空间坐标
     *
     * @param appFenceDTO
     */
    private void decodeFence(MachWarnFenceDTO appFenceDTO) {
        // 转换空间几何对象
        if (FenceType.POLYGON.value().equals(appFenceDTO.getType())) {
            Polygon polygon = GeometryUtil.decodePolygon(appFenceDTO.getGeometryWKT());
            appFenceDTO.setPolygonPointList(polygon.getPointList());
        }
        // 圆形
        else if (FenceType.CIRCLE.value().equals(appFenceDTO.getType())) {
            Point point = GeometryUtil.decodePoint(appFenceDTO.getGeometryWKT());
            appFenceDTO.setCenterPoint(point);
        }
    }

    /**
     * 编码空间坐标
     *
     * @param type
     * @param radius
     * @param centerPoint
     * @param polygonPointList
     * @return
     */
    private MachWarnFenceDTO encodeFence(Integer type, Double radius, Point centerPoint, List<Point> polygonPointList) {
        String geometryWKT = null;
        // 多边形
        if (FenceType.POLYGON.value().equals(type)) {
            if (polygonPointList == null || polygonPointList.size() < 3) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "多边形参数不正确!");
            }
            // 首位相连
            polygonPointList.add(polygonPointList.get(0));
            geometryWKT = GeometryUtil.encodePolygon(new Polygon(polygonPointList));
        }
        // 圆形
        else if (FenceType.CIRCLE.value().equals(type)) {
            if (centerPoint == null || radius == null) {
                throw new BizException(ResultEnum.FAILURE.getCode(), "圆形参数不正确!");
            }
            geometryWKT = GeometryUtil.encodePoint(centerPoint);
        }
        MachWarnFenceDTO data = new MachWarnFenceDTO();
        data.setGeometryWKT(geometryWKT);
        data.setType(type);
        data.setRadius(radius);
        return data;
    }

    /**
     * 提取ruleParam
     *
     * @return
     */
    private String getRuleParam(Integer ruleType, Integer type, Double radius, Point centerPoint, List<Point> polygonPointList, MachRotationRuleDTO machRotationRuleDTO, String ruleValue) {
        String ruleParam;
        if (AppMachWarnRuleType.ROTATION.value().equals(ruleType)) {
            // 倾角报警规则
            ruleParam = JSON.toJSONString(machRotationRuleDTO);
        } else if (AppMachWarnRuleType.FENCE.value().equals(ruleType)) {
            // 电子围栏报警规则
            MachWarnFenceDTO machWarnFenceDTO = this.encodeFence(type, radius, centerPoint, polygonPointList);
            ruleParam = JSON.toJSONString(machWarnFenceDTO);
        } else {
            Map<String, String> map = new HashMap<>();
            map.put(PARAM_NAME, ruleValue);
            ruleParam = JSON.toJSONString(map);
        }
        return ruleParam;
    }

    private String generateWarnDesc(AppMachWarnRuleType ruleType, MachWarnCheckDTO triggerParam, String ruleDesc) {
        if (AppMachWarnRuleType.ROTATION.equals(ruleType)) {
            return triggerParam.getTriggerValue();
        }
        if (AppMachWarnRuleType.FENCE.equals(ruleType) || AppMachWarnRuleType.OILPOS.equals(ruleType)
                || AppMachWarnRuleType.BATTERY.equals(ruleType) || AppMachWarnRuleType.ENGINE.equals(ruleType)
                || AppMachWarnRuleType.DEVICE.equals(ruleType)) {
            return ruleType.detail();
        }

        String value = triggerParam.getTriggerValue();
        ruleDesc = (StringUtils.isBlank(ruleDesc) || "暂无".equals(ruleDesc)) ? "" : ("(报警规则：" + ruleDesc + ")");
        if (AppMachWarnRuleType.IDLE.equals(ruleType) || AppMachWarnRuleType.STOP.equals(ruleType) || AppMachWarnRuleType.WORK.equals(ruleType)) {
            long seconds = Long.parseLong(value);
            StringBuilder sb = new StringBuilder();
            sb.append(ruleType.pic()).append("超时，已").append(ruleType.pic());
            sb.append(seconds < 60 ? (seconds + "秒") : (seconds / 60) + "分钟");
            sb.append(ruleDesc);
            return sb.toString();
        } else if (AppMachWarnRuleType.SPEED.equals(ruleType)) {
            return "速度为" + value + "km/h，已超速" + ruleDesc;
        } else if (AppMachWarnRuleType.FORCE.equals(ruleType)) {
            return "牵引力已达到" + value + "KN" + ruleDesc;
        } else {
            return "";
        }

    }

    private String generateRuleDesc(AppMachWarnRuleType ruleType, String ruleParam) {
        switch (ruleType) {
            case FENCE:
            case OILPOS:
            case BATTERY:
            case ENGINE:
            case DEVICE:
                return "暂无";
            case IDLE:
            case STOP:
            case WORK:
            case SPEED:
            case FORCE:
                String ruleValue = JSON.parseObject(ruleParam).getString(PARAM_NAME);
                return String.format(ruleType.detail(), ruleValue);
            case ROTATION:
                MachRotationRuleDTO rule = JSON.parseObject(ruleParam, MachRotationRuleDTO.class);
                StringJoiner joiner = new StringJoiner(",");
                if (rule.getPreRotationX() != null) {
                    joiner.add("前倾斜角度>" + rule.getPreRotationX() + "°");
                }
                if (rule.getPostRotationX() != null) {
                    joiner.add("后倾斜角度>" + rule.getPostRotationX() + "°");
                }
                if (rule.getLeftRotationZ() != null) {
                    joiner.add("左倾斜角度>" + rule.getLeftRotationZ() + "°");
                }
                if (rule.getRightRotationZ() != null) {
                    joiner.add("右倾斜角度>" + rule.getRightRotationZ() + "°");
                }
                String str = joiner.toString();
                str = str == null ? "" : str;
                return str;
            default:
                return "";
        }
    }

}
